#region (c) 2014 THN Solutions LLC. - All rights reserved
/*
THN TELEPORT version 2

Copyright (c) 2014, THN Solutions LLC. ( www.ThnSolutions.com )
Author: Nguyễn, M. Hải                 ( www.Minh-Hai.com     )
All rights reserved.

This library is dual-licensed.
  + For commercial software, please obtain a commercial license from THN Solutions LLC.

  + For free software, this library is licensed under GPL version 3. A summary of GPLv3 is
    listed below. You should also find a copy of GPLv3 as file License_GPLv3.txt included
	with the source-code files.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 3 as published by
    the Free Software Foundation  of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#endregion

#region Using directives
using System;
#endregion

namespace Thn.Communication.Teleporting
{
	/// <summary>
	/// Static interface for "teleporting" objects
	/// </summary>
	public class Teleport
    {
        /// <summary>
        /// Whether types has been registered.
        /// </summary>
        internal static bool IsConnectorTypesRegistered = false;

        #region Register Types
        /// <summary>
        /// Register all types in Teleporting.Connectors.* namespace.
        /// </summary>
        internal static void RegisterConnectorTypes()
        {
            if (!IsConnectorTypesRegistered)
            {
                TypeResolver.RegisterAllTypes(typeof(Teleport), "Thn.Communication.Teleporting.Connectors.*");
            }
            #region Defensive tracing
            else
            {
                //already registered, no need to do it again
            }
            #endregion
        }
        #endregion

        #region Singleton Instance
        /// <summary>
		/// Static variable for thread locking
		/// </summary>
		static object SyncRoot = new object();
		
		/// <summary>
		/// Actual static variable for Instance
		/// </summary>
		static Teleport mInstance = null;
		
		/// <summary>
		/// Gets the static instance of this class
		/// </summary>
		static Teleport Instance
		{
			get
			{
				if (mInstance == null)
				{
					//initialize new instance
					Teleport tmp = new Teleport();
					
					//assign to static variable. Lock root for thread-safe locking
					lock (SyncRoot)
					{
						mInstance = tmp;
					}
				}

				return mInstance;
			}
		}
        #endregion
		
        #region Constructor
        /// <summary>
        /// Default constructor
        /// <para>this constructor is deliberately private so that it cannot be instantiated by anyone else but itself.</para>
        /// </summary>		
		Teleport()
        {
            mTeleporter = new Teleporter();
            RegisterConnectorTypes();            
        }
		#endregion

		#region Teleporter
		private ITeleporter mTeleporter;

		/// <summary>
		/// Gets/Sets the teleporter which handles teleportation
		/// </summary>
		public static ITeleporter Teleporter
		{
			get { return Instance.mTeleporter; }
			set { Instance.mTeleporter = value; }
		}	
		#endregion

		#region Add Gateway
		/// <summary>
		/// Registers the target object for remote invoking
		/// </summary>
		public static void AddGateway(string gateway, object value)
		{
			Instance.mTeleporter.AddGateway(gateway, value);
		}
        #endregion

        #region Request
        /// <summary>
		/// Beams a request to the other gateway
		/// </summary>
		/// <param name="Gateway">Name of target gateway</param>
		/// <param name="Method">Name of methods</param>
		/// <param name="Values">Arguments</param>
		/// <returns>Returned results</returns>
        [System.Diagnostics.DebuggerHidden]
		public static object Request(string Gateway, string Method, params object[] Values)
		{
			return Instance.mTeleporter.Request(Gateway, Method, Values);
		}
		#endregion
	}
}
